/* Declarations for the coroutine type.

   This file is part of khipu.

   khipu is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

#ifndef __KP_CORO__
#define __KP_CORO__   1

#include "interp.hpp"

KP_DECLS_BEGIN

struct coroutine : public varobj
{
  static const int code = typecode::CORO;
  static coroutine* alloc_raw ();
  static object make (interpreter *interp, uint32_t bp);

  object value;
  object argv;
  object dbinds;
  int ip_offset;
  int sp_diff;
  uint32_t frame;
  uint32_t exc_off;

  bool valid_p () const
    {
      return (this->ip_offset >= 0);
    }

  void mark_invalid ()
    {
      this->ip_offset = -1;
    }
};

inline bool coro_p (object obj)
{
  return (itype (obj) == typecode::CORO);
}

inline coroutine* as_coro (object obj)
{
  return ((coroutine *)unmask (obj));
}

KP_EXPORT object alloc_coroutine (interpreter *interp);

// Resume execution of a coroutine.
KP_EXPORT object call_coroutine (interpreter *interp,
  coroutine *crp, object value);

// Entry point for the above call.
KP_EXPORT object coro_next (interpreter *interp, object *argv, int argc);

struct stream;
struct io_info;
struct pack_info;

// Pack a coroutine into a stream.
KP_EXPORT int pack_G (interpreter *interp,
  stream *strm, object obj, pack_info& info);

// Unpack a coroutine from a stream.
KP_EXPORT object unpack_G (interpreter *interp,
  stream *strm, pack_info& info, bool save);

KP_DECLS_END

#endif
